iT邦幫忙

2022 iThome 鐵人賽

DAY 20
1
Modern Web

淺入淺出 Rails with Vue系列 第 20

【Day 20】淺入淺出 Rails with Vue - Vue 的基本概念 - 19

  • 分享至 

  • xImage
  •  

前言

本系列將介紹 Rails with Vue 的基本概念,並且以一個簡單的專案 Todo 來說明如何使用 Rails with Vue。我將透過這一系列的文章記錄我學習的過程,並且將我所學到的知識分享給大家。

Components Basics

Listening to Child Components Events

Emitting a Value With an Event

在前一篇文章中,我們已經知道如何在 child component 中觸發事件,並且在 parent component 中監聽事件,在這樣的 use case 中,text 要放大多少是透過 parent component 來決定的,但是如果我們想要讓 child component 來決定要放大多少呢?
此時就可以使用 $emit 的第二個參數來傳遞值,如以下範例中,我們在 child component 中觸發 enlargeText 事件時,同時傳遞了 0.1 這個值,這個值就會被 parent component 接收到。

<button v-on:click="$emit('enlarge-text', 0.1)">
  Enlarge text
</button>

當 parent component 監聽到 enlarge-text 事件時,就可以透過 $event 來取得傳遞的值。

<blog-post
  ...
  v-on:enlarge-text="postFontSize += $event"
></blog-post>

又或者假如 parent component 的 event handler 是一個 method 時,

<blog-post
  ...
  v-on:enlarge-text="onEnlargeText"
></blog-post>

$event 的值就會被當作 method 的第一個參數傳入,如以下範例中,$event 的值就會被當作 enlargeAmount 這個參數傳入。

methods: {
  onEnlargeText: function (enlargeAmount) {
    this.postFontSize += enlargeAmount
  }
}

Using v-model on Components

custom event 也可以透過 v-model 來建立 custom inputs。
首先讓我們先回想一下 v-model 是如何使用的,如以下範例:

<input v-model="searchText">

當我們在 input 上使用 v-model 時,Vue 會在背後幫我們做以下的事情:

  1. 在 input 上建立一個 value attribute,並且將它的值綁定到一個名為 searchText 的 data property 上。
  2. 在 input 上建立一個 input event listener,當 input 的值被改變時,就會觸發這個 listener,並且將新的值傳遞給 searchText
<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>

按照上述的範例,我們嘗試套用到 custom component 上時,會發現無法正常運作,

<custom-input
  v-bind:value="searchText"
  v-on:input="searchText = $event"
></custom-input>

原因是因為在 custom component 中,我們並沒有 value attribute,所以會造成無法正常運作的狀況,
為了讓 custom component 可以正常運作,必須滿足以下兩個條件:

  1. 在 custom component 上建立一個 value prop,並且將它的值綁定到一個名為 value 的 prop 上。
  2. 在 custom component 上建立一個 input event listener,當 custom component 的值被改變時,就會觸發這個 listener,並且將新的值傳遞給 value
Vue.component('custom-input', {
  props: ['value'],
  template: `
    <input
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)"
    >
  `
})

這樣一來,我們就可以在 parent component 中使用 v-model 來建立 custom inputs。

<custom-input v-model="searchText"></custom-input>

Content Distribution with Slots

有時候我們會需要在 custom component 中嵌入一些 content,如以下範例:

<alert-box>
  Something bad happened.
</alert-box>

期望他可以渲染成以下的 HTML:

<div id="slots-demo" class="demo">
  <div class="demo-alert-box">
    <strong>Error!</strong>
    Something bad happened.
  </div>
</div>

這時候我們就可以使用 <slot> 來建立一個可以嵌入 content 的位置。

Vue.component('alert-box', {
  template: `
    <div class="demo-alert-box">
      <strong>Error!</strong>
      <slot></slot>
    </div>
  `
})

Reference


上一篇
【Day 19】淺入淺出 Rails with Vue - Vue 的基本概念 - 18
下一篇
【Day 21】淺入淺出 Rails with Vue - Vue 的基本概念 - 20
系列文
淺入淺出 Rails with Vue30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言